#pragma once

//////////////////////////////////////////////////////////////////////////
//
//   Camera used to traverse 3D world.
//   It has the most common camera functionalities.
//
//////////////////////////////////////////////////////////////////////////

#include <DirectXMath.h>

class Camera {
    // Cache View/Projection matrices.
    DirectX::XMFLOAT4X4A mView;
    DirectX::XMFLOAT4X4A mProj;

    // Camera coordinate system with coordinates 
    // relative to world space.
    DirectX::XMFLOAT3A mPosW;
    DirectX::XMFLOAT3A mRightW;
    DirectX::XMFLOAT3A mUpW;
    DirectX::XMFLOAT3A mLookW;

    // Cache frustum properties.
    float mNearZ;
    float mFarZ;
    float mAspectRatio;
    float mFovY;
    float mNearPlaneY;
    float mFarPlaneY;

public:
    Camera();

    void setFrustrum(const float fovY, const float aspect, const float nearPlaneZ, const float farPlaneZ);

    void setCoordinateSystem(DirectX::FXMVECTOR posW, DirectX::FXMVECTOR targetW, DirectX::FXMVECTOR upW);

    // Positive delta to strafe to right
    // Negative delta to strafe to left
    void strafe(const float distance);

    // Positive delta to walk forward
    // Negative delta to walk backward
    void walk(const float distance);

    // Angle is in counterclockwise order
    // from x axis to z axis
    void pitch(const float angle);

    // Angle is in counterclockwise order
    // from x axis to z axis
    void rotateAboutYAxis(const float angle);

    // Positive delta to go up
    // Negative delta to go down
    void translateThroughYAxis(const float distance);

    // This function should be called once per frame
    // before asking for view projection matrix
    void updateViewMatrix();

	DirectX::XMMATRIX viewProjMatrix() const;
	DirectX::XMMATRIX viewMatrix() const;
	DirectX::XMMATRIX projMatrix() const;

	DirectX::XMFLOAT3A& worldPosition() { return mPosW; }
	DirectX::XMFLOAT3A& worldLookVector() { return mLookW; }
};

